package ru.mcfr.oxygen.updater.web;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import ru.mcfr.oxygen.updater.Version;
import ru.mcfr.oxygen.updater.utils.Streamer;
import ru.mcfr.oxygen.updater.utils.Zipper;
import sun.net.www.protocol.http.HttpURLConnection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

/**
 * Created by IntelliJ IDEA.
 * User: ws
 * Date: 28.04.11
 * Time: 15:28
 * To change this template use File | Settings | File Templates.
 */
public class XMLBasedUpdater extends AbstractConnector{

    private Vector<Map<String, String>> packages;

    public XMLBasedUpdater(Properties p) {
        super(p);
    }

    @Override
    public InputStream get(String url) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public boolean checkUpdates(HttpURLConnection urlConn) {
		DataInputStream input;
        this.packages = new Vector<Map<String, String>>();
		try {
			if (urlConn == null) return false;
			input = new DataInputStream (urlConn.getInputStream ());
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(input);

			input.close ();
			urlConn.disconnect();

            parseXmlResponse(doc,props.getProperty("trunk", "stable"));

            int not_used = 0;
            for (Map<String,String> info : packages){
                String base_path = "";
                if (info.get("type").equalsIgnoreCase("frameworks"))
                    base_path = props.getProperty("path-to-framework");
                else
                    base_path = props.getProperty("path-to-plugin");

                String path = base_path + File.separator + info.get("package");

                if (new File(path).exists()){
                    Version existVersion = Version.fromDir(path);

                    if (existVersion == null | existVersion.compareTo(info.get("version")) > -1){
                        info.put("not-use","true");
                        not_used++;
                    }
                }
            }

            if (not_used == packages.size())
                return false;
            return true;

		}catch (IOException e) {
			logger.error(e.getLocalizedMessage());
		} catch (ParserConfigurationException e) {
			logger.error(e.getLocalizedMessage());
		} catch (SAXException e) {
			logger.error(e.getLocalizedMessage());
		}
		return false;
	}

    private void parseXmlResponse(Document resp, String filter){

        NodeList entrys = resp.getElementsByTagName("entry");
        for (int i = 0; i < entrys.getLength(); i ++){
            Element entry = (Element) entrys.item(i);
            Map<String, String> info = new HashMap<String, String>();
            info.put("version", entry.getAttribute("version"));
            info.put("path", entry.getAttribute("path"));
            Element branch = (Element) entry.getParentNode();
            info.put("branch", branch.getAttribute("name"));
            Element package_ = (Element) branch.getParentNode();
            info.put("package", package_.getAttribute("name"));
            info.put("type", package_.getAttribute("type"));
            if (filter.contains(branch.getAttribute("name")))
                packages.add(info);
        }

    }

    //only download to storage actual versions
    public Map<String,String> downloadUpdatesTo(String destMainRelative){

        Map <String, String> res = new HashMap<String, String>();

        //if dest places in main subfolders
        destMainRelative = destMainRelative.replace("\\",File.separator).replace("/", File.separator);

        for (Map<String,String> packageInfo : packages) {

            if (packageInfo.keySet().contains("not-use")) continue;

            // updates/[type]/[name]/[version]/
            File destFolder = new File(props.getProperty("path-to-main") +
                    File.separator + destMainRelative +
                    File.separator + packageInfo.get("type") +
                    File.separator + packageInfo.get("package") +
                    File.separator + packageInfo.get("version"));

            destFolder.mkdirs();

            try {

                HttpURLConnection urlConn = connectToURL(props.getProperty("server-url") + packageInfo.get("path"));
                String fileName = urlConn.getURL().getFile();

                //get file name from url
                String[] tmp = fileName.split("\\?")[0].split("\\/");
                fileName = tmp[tmp.length-1];

                if (urlConn != null) {
                    File destFile = new File(destFolder.getAbsolutePath() + File.separator + fileName);
                    Streamer.downloadFromStream(urlConn.getInputStream(), destFile);
                    urlConn.disconnect();
                    Zipper.unzip(destFile, destFolder.getAbsolutePath());

                    // install to[key] from[value]
                    res.put(packageInfo.get("type"), destFolder.getAbsolutePath());
                }

            } catch (IOException e) {
                logger.error(e.getLocalizedMessage());
            }
        }
        return res;
	}
}
